package service

import (
	"github.com/gogf/gf/errors/gerror"
	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/net/ghttp"
	"golang.org/x/crypto/bcrypt"
	"shrimp-blog-server/app/dao"
	"shrimp-blog-server/app/model"
	"shrimp-blog-server/utils"
	"strings"
	"time"
)

func (server UserService) Login(req *ghttp.Request, email, password string) {
	user := dao.User.GetUserByEmail(email)

	if user.Id == 0 {
		responses.ErrorResponseExit(req, "用户不存在,请先注册")
	}

	err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password))
	if err != nil {
		responses.ErrorResponseExit(req, "密码错误")
	}

	// 设置session与上下文变量
	ctxUser := &dao.CtxUser{
		ID:       user.Id,
		UserName: user.Username,
		Email:    user.Email,
		Status:   user.Status,
		Avatar:   user.Avatar,
	}
	// 生成token
	customClaims := utils.CustomClaims{
		ID:       user.Id,
		Email:    user.Email,
		Username: user.Username,
	}

	req.Session.Set("user", ctxUser)
	req.Cookie.SetSessionId(req.GetSessionId())

	dao.AppCtx.SetUser(req.Context(), ctxUser)

	timeEx := time.Now().Add(10 * time.Minute)
	token, err := utils.CreateToken(customClaims, timeEx)
	if err != nil {
		panic(gerror.Wrap(err, "注册生成token失败"))
	}
	if strings.Contains(req.URL.Path, "admin") {
		// 获取角色
		var role model.Role

		err = dao.Role.DB().Model(dao.Role.Table).Where("id = ?", dao.UserRole.DB().Model(dao.UserRole.Table).Fields(dao.UserRole.Columns.RoleId).Where(dao.UserRole.Columns.UserId, user.Id)).Scan(&role)
		if err != nil {
			panic(gerror.Wrap(err, "获取角色失败"))
		}
		responses.Json(req, successCode, successMessage, g.Map{
			"user":   customClaims,
			"token":  token,
			"role":   RoleMap[role.Name],
			"expire": timeEx,
		})
	} else {
		responses.Json(req, successCode, successMessage, g.Map{
			"user":   customClaims,
			"token":  token,
			"expire": timeEx,
		})
	}

}
func (server UserService) Register(req *ghttp.Request, username, email, password string) {
	user := dao.User.GetUserByEmail(email)

	if user.Email != "" {
		responses.ErrorResponseExit(req, "用户已存在")
	}

	encryptPasswordBytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
	if err != nil {
		g.Log("Register").Error(err)
		panic(err)
	}

	user = model.User{
		Username: username,
		Email:    email,
		Password: string(encryptPasswordBytes),
		Status:   model.ShowStatus,
	}

	id, err := dao.User.InsertUserAndGetId(&user)
	if err != nil {
		g.Log("Register").Error(err)
		panic(err)
	}
	if id == 0 {
		responses.ErrorResponseExit(req, "注册失败")
	}

	_, err = dao.UserRole.Insert(model.UserRole{
		UserId: uint(id),
		RoleId: User.Id,
		Status: 1,
	})
	if err != nil {
		g.Log("Register:注册用户角色关联问题").Error(err)
		panic(err)
	}
	responses.SuccessResponse(req)
}

func (server UserService) Insert(req *ghttp.Request, user ...model.User) {
	encryptPasswordBytes, err := bcrypt.GenerateFromPassword([]byte("123456"), bcrypt.DefaultCost)
	if err != nil {
		g.Log("插入用户").Error(err)
		panic(err)
	}
	for i := range user {
		user[i].Password = string(encryptPasswordBytes)
		user[i].Status = 1
	}

	affectRow, err := dao.User.Insert(user...)
	if err != nil {
		g.Log("Insert").Error(err)
		panic(err)
	}
	if affectRow == 0 {
		responses.ErrorResponseExit(req, "用户添加失败")
	}
	responses.SuccessResponse(req)
}

// Update 更新用户信息
func (server UserService) Update(req *ghttp.Request, user ...model.User) {
	ids := make([]uint, len(user))
	for i := range user {
		ids[i] = user[i].Id
	}

	userFind, err := dao.User.GetUserById(ids...)
	if err != nil {
		g.Log("更新用户信息").Error(err)
		responses.ErrorResponseExit(req, "更新操作查询数据失败")
	}

	if userFind == nil {
		responses.ErrorResponseExit(req, "用户不存在")
	}
	if (userFind)[0].Status == 0 || (userFind)[0].DeleteTime != nil {
		responses.ErrorResponseExit(req, "用户已删除")
	}
	affectRow, err := dao.User.Update(user...)
	if err != nil {
		g.Log("更新用户信息").Error(err)
		panic(err)
	}
	if affectRow == 0 {
		responses.ErrorResponseExit(req, "更新用户信息失败")
	}
	responses.SuccessResponse(req)
}

// Delete 删除用户
func (server UserService) Delete(req *ghttp.Request, id ...uint) {
	user, err := dao.User.GetUserById(id...)
	if err != nil {
		g.Log("删除用户").Error(err)
		responses.ErrorResponseExit(req, "删除操作查询数据失败")
	}
	if user == nil {
		responses.ErrorResponseExit(req, "用户不存在")
	}

	userModel := make([]model.User, len(user))
	copy(userModel, user)
	result, err := dao.User.Delete(userModel...)
	if err != nil {
		g.Log("删除用户").Error(err)
		panic(err)
	}
	if result == 0 {
		responses.ErrorResponseExit(req, "删除用户失败")
	}

	responses.SuccessResponse(req)
}

func (server UserService) GetUserByID(req *ghttp.Request, id ...uint) {
	user, err := dao.User.GetUserById(id...)

	if err != nil {
		g.Log("根据id查询用户信息").Error(err)
		panic(err)
	}
	if user == nil {
		responses.ErrorResponseExit(req, "用户不存在")
	}
	responses.Json(req, successCode, successMessage, user)
}

func (server UserService) AlterPassword(req *ghttp.Request, email, password string) {
	user := dao.User.GetUserByEmail(email)
	if user.Email == "" {
		responses.ErrorResponseExit(req, "用户不存在")
	}
	encryptPasswordBytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
	if err != nil {
		g.Log("用户修改密码").Error(err)
		panic(err)
	}
	user.Password = string(encryptPasswordBytes)
	affectRow, err := dao.User.Update(user)
	if err != nil {
		g.Log("用户修改密码").Error(err)
		panic(err)
	}
	if affectRow == 0 {
		responses.ErrorResponseExit(req, "密码修改失败")
	}
	responses.SuccessResponse(req)
}

func (server UserService) GetUserPage(req *ghttp.Request, page model.Page) {
	result, err := dao.User.GetUsersByPage(page.Page, page.Size)
	if err != nil {
		panic(gerror.Wrap(err, "查询标签失败"))
	}
	if result == nil {
		responses.ErrorResponseExit(req, "用户列表为空")
	}
	userResponsePage := result[0].ConvertPage(result, page)
	userResponsePage.Page.Total, err = dao.User.DB().Model(dao.Label.Table).Count()
	if err != nil {
		panic(gerror.Wrap(err, "统计数量失败"))
	}
	responses.Json(req, successCode, successMessage, userResponsePage)
}
